package com.wuyou.sso.service.impl;

import com.wuyou.sso.common.utils.BeanUtils;
import com.wuyou.sso.component.CustomizedTokenServices;
import com.wuyou.sso.domain.dto.UsernamePasswordLoginDTO;
import com.wuyou.sso.service.LoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.*;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * LoginServiceImpl
 *
 * @Date 2025/4/27 15:38
 * @Author 无忧
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {
    private ClientDetails client;

    private final UserDetailsService userDetailsService;
    //    private final OAuth2RequestFactory oAuth2RequestFactory;
    private final ClientDetailsService clientDetailsService;
    private final AuthenticationManager authenticationManager;
    //    private final UserDetailsChecker userDetailsChecker;
    private final CustomizedTokenServices tokenService = new CustomizedTokenServices();


    @Override
    public OAuth2AccessToken login(UsernamePasswordLoginDTO loginDTO) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(loginDTO.getUsername());
        if (userDetails == null) {
            // 不管什么原因查询不到对应值，从安全角度而言都先欺骗一下调用方用户名或密码错误
            throw new BadCredentialsException("用户名或密码错误");
        }
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword());
        Map<String, String> parameters = BeanUtils.beanToStringMap(loginDTO);
        TokenRequest tokenRequest = new TokenRequest(BeanUtils.beanToStringMap(loginDTO), "test01", Arrays.asList("server"), "password");


        Authentication authResult = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authResult;
        OAuth2Request oAuth2Request = createOAuth2Request(parameters);
        OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authenticationToken);
        OAuth2AccessToken accessToken = tokenService.createAccessToken(oAuth2Authentication);
        return accessToken;
    }

    private OAuth2Request createOAuth2Request(Map<String, String> requestParameters) {
        HashMap<String, String> modifiable = new HashMap<String, String>(requestParameters);
        // Remove password if present to prevent leaks
        modifiable.remove("password");
        modifiable.remove("client_secret");
        // Add grant type so it can be retrieved from OAuth2Request
//        modifiable.put("grant_type", grantType);
//        return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, this.getScope(),
//                client.getResourceIds(), null, null, null);

        this.client = clientDetailsService.loadClientByClientId("");
        return new OAuth2Request(modifiable, client.getClientId(), client.getAuthorities(), true, new HashSet<>(Arrays.asList("server")),
                client.getResourceIds(), null, null, null);
    }
}
